﻿using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Text;

namespace Accumulation.Common {
    /// <summary>
    /// 常用方法
    /// <remarks>
    /// MatchZhou - 2009/1/19
    /// </remarks>
    /// </summary>
    public class Methods {
        /// <summary>
        /// 将为空或null的字符串转化成指定格式
        /// </summary>
        /// <typeparam name="T">类型，例：int</typeparam>
        /// <param name="s">字符串</param>
        /// <param name="defaultValue">缺省值</param>
        /// <returns>指定类型的值</returns>
        public static T ConvertTo<T>(string s, T defaultValue) {
            return string.IsNullOrEmpty(s)
                ? defaultValue
                : (T)Convert.ChangeType(s, typeof(T));
        }
        /// <summary>
        /// 获得字符串长度，区分单字节和双字节
        /// </summary>
        /// <param name="str">字符串</param>
        /// <returns>字符串长度</returns>
        public static int LengthString(string str) {
            byte[] bytes = Encoding.Unicode.GetBytes(str);
            int index = 0, currentLength = 0;
            for (int i = 0; i < bytes.Length; i++) {
                index = (int)(i * 2 + 1);
                if (index > bytes.Length) { break; }
                currentLength += bytes[index] > 0 ? 2 : 1;
            }
            return currentLength;
        }
        /// <summary>
        /// 截取指定长度的字符串，区分单字节和双字节
        /// </summary>
        /// <param name="str">截取的字符串</param>
        /// <param name="length">截取的长度</param>
        /// <returns>指定截取长度后的字符串</returns>
        public static string SubString(string str, int length) {
            int trimLength = length * 2;
            byte[] strByte = Encoding.Unicode.GetBytes(str.Trim());
            if (strByte.Length <= trimLength) { return str; }
            int index = 0, currentLength = 0;
            for (int i = 0; i < length; i++) {
                index = (int)(i * 2 + 1);
                currentLength += strByte[index] > 0 ? 1 : 2;
                if (currentLength >= str.Length) { break; }
            }
            return str.Substring(0, currentLength < str.Length ? currentLength : str.Length) + " ...";
        }
        /// <summary>
        /// 装载图片并且防止图片被锁定
        /// http://support.microsoft.com/kb/311754/EN-US/
        /// </summary>
        /// <param name="photoPath">图片路径</param>
        /// <returns>Image</returns>
        public static Image LoadImage(string photoPath) {
            using (FileStream stream = new FileStream(photoPath, FileMode.Open, FileAccess.Read)) {
                using (BinaryReader reader = new BinaryReader(stream)) {
                    // 取得所有的图片数据   
                    byte[] buffer = new byte[stream.Length];
                    reader.Read(buffer, 0, (int)stream.Length);
                    // 然后创建一个内存中的 Stream 对象去生成图片   
                    // 这样文件就不会被锁定了   
                    using (MemoryStream ms = new MemoryStream(buffer)) {
                        return Image.FromStream(ms);
                    }
                }
            }
        }
        /// <summary>
        /// 生成指定大小的图片，按照指定的大小等比例缩放
        /// </summary>
        /// <param name="thumbWidth">宽</param>
        /// <param name="thumbHeight">高</param>
        /// <param name="photoPath">图片路径</param>
        /// <param name="isFixed">如果图片小于生成的指定大小，是不是用原图的大小替换指定的大小</param>
        /// <param name="isHighQulity">是否启用无损压缩，高质量生成的文件自然大了</param>
        /// <param name="contentType">文件类型</param>
        /// <returns>MemoryStream</returns>
        public static MemoryStream ThumbPhoto(int thumbWidth, int thumbHeight, string photoPath, bool isFixed, bool isHighQulity, out string contentType) {
            Image img = LoadImage(photoPath);
            return Methods.ThumbPhoto(thumbWidth, thumbHeight, img, isFixed, isHighQulity, out contentType);
        }
        /// <summary>
        /// 生成指定大小的图片，按照指定的大小等比例缩放
        /// </summary>
        /// <param name="thumbWidth">宽</param>
        /// <param name="thumbHeight">高</param>
        /// <param name="photoPath">图片路径</param>
        /// <param name="isFixed">如果图片小于生成的指定大小，是不是用原图的大小替换指定的大小</param>
        /// <param name="isHighQulity">是否启用无损压缩，高质量生成的文件自然大了</param>
        /// <returns>MemoryStream</returns>
        public static MemoryStream ThumbPhoto(int thumbWidth, int thumbHeight, string photoPath, bool isFixed, bool isHighQulity) {
            string contentType;
            Image img = LoadImage(photoPath);
            return Methods.ThumbPhoto(thumbWidth, thumbHeight, img, isFixed, isHighQulity, out contentType);
        }
        /// <summary>
        /// 生成指定大小的图片，按照指定的大小等比例缩放，
        /// 如果图片小于生成的指定大小，用原图的大小替换指定的大小，生成高质量的无损压缩图片
        /// </summary>
        /// <param name="thumbWidth">宽</param>
        /// <param name="thumbHeight">高</param>
        /// <param name="photoPath">图片路径</param>
        /// <returns>MemoryStream</returns>
        public static MemoryStream ThumbPhoto(int thumbWidth, int thumbHeight, string photoPath) {
            string contentType;
            Image img = LoadImage(photoPath);
            return Methods.ThumbPhoto(thumbWidth, thumbHeight, img, true, true, out contentType);
        }
        /// <summary>
        /// 生成指定大小的图片，按照指定的大小等比例缩放
        /// </summary>
        /// <param name="thumbWidth">宽</param>
        /// <param name="thumbHeight">高</param>
        /// <param name="fileStream">文件流</param>
        /// <param name="isFixed">如果图片小于生成的指定大小，是不是用原图的大小替换指定的大小</param>
        /// <param name="isHighQulity">是否启用无损压缩，高质量生成的文件自然大了</param>
        /// <param name="contentType">文件类型</param>
        /// <returns>MemoryStream</returns>
        public static MemoryStream ThumbPhoto(int thumbWidth, int thumbHeight, Stream fileStream, bool isFixed, bool isHighQulity, out string contentType) {
            Image img = Image.FromStream(fileStream);
            return Methods.ThumbPhoto(thumbWidth, thumbHeight, img, isFixed, isHighQulity, out contentType);
        }
        /// <summary>
        /// 生成指定大小的图片，按照指定的大小等比例缩放,
        /// 如果图片小于生成的指定大小，用原图的大小替换指定的大小，生成高质量的无损压缩图片
        /// </summary>
        /// <param name="thumbWidth">宽</param>
        /// <param name="thumbHeight">高</param>
        /// <param name="fileStream">文件流</param>
        /// <returns>MemoryStream</returns>
        public static MemoryStream ThumbPhoto(int thumbWidth, int thumbHeight, Stream fileStream) {
            string contentType;
            Image img = Image.FromStream(fileStream);
            return Methods.ThumbPhoto(thumbWidth, thumbHeight, img, true, true, out contentType);
        }
        /// <summary>
        /// 生成指定大小的图片，按照指定的大小等比例缩放
        /// </summary>
        /// <param name="thumbWidth">宽</param>
        /// <param name="thumbHeight">高</param>
        /// <param name="fileStream">文件流</param>
        /// <param name="isFixed">如果图片小于生成的指定大小，是不是用原图的大小替换指定的大小</param>
        /// <param name="isHighQulity">是否启用无损压缩，高质量生成的文件自然大了</param>
        /// <returns>MemoryStream</returns>
        public static MemoryStream ThumbPhoto(int thumbWidth, int thumbHeight, Stream fileStream, bool isFixed, bool isHighQulity) {
            string contentType;
            Image img = Image.FromStream(fileStream);
            return Methods.ThumbPhoto(thumbWidth, thumbHeight, img, isFixed, isHighQulity, out contentType);
        }
        /// <summary>
        /// 获取图片 contentType
        /// </summary>
        /// <param name="format">ImageFormat</param>
        /// <returns>contentType</returns>
        public static string FileContentType(ImageFormat format) {
            if (format == ImageFormat.Jpeg) { return "image/jpeg"; }
            if (format == ImageFormat.Gif) { return "image/gif"; }
            if (format == ImageFormat.Png) { return "image/png"; }
            return "image/jpeg";
        }
        // 生成指定小的图片
        private static MemoryStream ThumbPhoto(int thumbWidth, int thumbHeight, Image img, bool isFixed, bool isHighQulity, out string contentType) {
            contentType = Methods.FileContentType(img.RawFormat);
            // 计算缩放比例或大小
            int x, y, w, h;
            double rate;
            // 生成正方形的比例图
            if (thumbWidth == thumbHeight) {
                if (img.Width >= thumbWidth & img.Height >= thumbHeight) {
                    if (img.Width == img.Height) {
                        w = thumbWidth;
                        h = thumbHeight;
                        x = y = 0;
                    }
                    else if (img.Width > img.Height) {
                        rate = img.Height / (double)thumbHeight;
                        w = (int)Math.Floor(img.Width / rate);
                        h = thumbHeight;
                        x = (int)Math.Floor((thumbWidth - w) / 2.0);
                        y = 0;
                    }
                    else {
                        rate = img.Width / (double)thumbWidth;
                        w = thumbWidth;
                        h = (int)Math.Floor(img.Height / rate);
                        x = 0;
                        y = (int)Math.Floor((thumbHeight - h) / 2.0);
                    }
                }
                else {
                    if (isFixed) {
                        if (img.Width < thumbWidth) { thumbWidth = img.Width; }
                        if (img.Height < thumbHeight) { thumbHeight = img.Height; }
                    }
                    w = img.Width;
                    h = img.Height;
                    x = (int)Math.Floor((thumbWidth - img.Width) / 2.0);
                    y = (int)Math.Floor((thumbHeight - img.Height) / 2.0);
                }
            }
            else {
                // 生成长方形的比例图
                if (img.Width >= thumbWidth & img.Height >= thumbHeight) {
                    if (img.Width == img.Height) {
                        rate = img.Height / (double)thumbHeight;
                        w = (int)Math.Floor(img.Width / rate);
                        h = (int)Math.Floor(img.Height / rate);
                        x = (int)Math.Floor((thumbWidth - w) / 2.0);
                        y = (int)Math.Floor((thumbHeight - h) / 2.0);
                    }
                    else if (img.Width > img.Height) {
                        rate = img.Height / (double)thumbHeight;
                        w = (int)Math.Floor(img.Width / rate);
                        h = thumbHeight;
                        x = (int)Math.Floor((thumbWidth - w) / 2.0);
                        y = 0;
                    }
                    else {
                        rate = img.Width / (double)thumbWidth;
                        w = thumbWidth;
                        h = (int)Math.Floor(img.Height / rate);
                        x = 0;
                        y = (int)Math.Floor((thumbHeight - h) / 2.0);
                    }
                }
                else {
                    if (isFixed) {
                        if (img.Width < thumbWidth) { thumbWidth = img.Width; }
                        if (img.Height < thumbHeight) { thumbHeight = img.Height; }
                    }
                    w = img.Width;
                    h = img.Height;
                    x = (int)Math.Floor((thumbWidth - img.Width) / 2.0);
                    y = (int)Math.Floor((thumbHeight - img.Height) / 2.0);
                }
            }
            // 缩略图大小
            Bitmap b = new Bitmap(thumbWidth, thumbHeight);
            // 新建画布
            Graphics g = Graphics.FromImage(b);
            // 设置画布的描绘质量
            g.CompositingQuality = CompositingQuality.HighQuality;
            // 设置高质量插值法
            g.InterpolationMode = InterpolationMode.High;
            // 设置高质量,低速度呈现平滑程度
            g.SmoothingMode = SmoothingMode.HighQuality;
            // 清空画布并以白色填充
            g.Clear(Color.White);
            // 画图
            g.DrawImage(img,
                x == 0 ? x - 1 : x,
                y == 0 ? y - 1 : y,
                x == 0 ? w + 1 : w,
                y == 0 ? h + 1 : h);

            try {
                MemoryStream ms = new MemoryStream();
                if (isHighQulity) {
                    // 以下代码为保存图片时，设置压缩质量
                    EncoderParameters encoderParams = new EncoderParameters();
                    long[] quality = new long[1];
                    quality[0] = 100;

                    EncoderParameter encoderParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
                    encoderParams.Param[0] = encoderParam;

                    //获得包含有关内置图像编码解码器的信息的 ImageCodecInfo 对象。
                    ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders();
                    ImageCodecInfo jpegICI = null;
                    for (int i = 0; i < arrayICI.Length; i++) {
                        if (arrayICI[i].FormatDescription.Equals("JPEG")) {
                            jpegICI = arrayICI[i]; //设置JPEG编码
                            break;
                        }
                    }
                    if (jpegICI != null) {
                        b.Save(ms, jpegICI, encoderParams);
                    }
                    else {
                        b.Save(ms, img.RawFormat);
                    }
                }
                else {
                    b.Save(ms, img.RawFormat);
                }
                return ms;
            }
            catch {
                return null;
            }
            finally {
                b.Dispose();
                g.Dispose();
            }
        }
    }
}
